#ifndef QUAT_H_
#define QUAT_H_

#include "geometry.hpp"
#include <iostream>

/** 
 * Unit quaternion class for rotation calculations.
 * Quaternion q is represented by scalar w and vector x, y, z.
 * @note Calculations are only valid for unit quaternions.
 * @sa Vector::operator *= (const class Quaternion &q)
 */
class Quaternion {
public:
    /// the scalar part
    float                     w;
    float                     x, y, z;

    /// create identity quaternion (w,x,y,z)=(1,0,0,0) (represents no rotation)
    Quaternion();
    /// create from vector and scalar
    Quaternion(float w, float x, float y, float z);
    /// create from vector and scalar
    Quaternion(const Vector &v, float w=0);
    /// represent rotation of angle theta [radians] by axis axis
    Quaternion(float theta, const Vector &axis);

    void                      normalize();
    /// set current values to represent rotation of given yaw, pitch and roll
    void                      set_yaw_pitch_roll(float yaw, float pitch, float roll);

    Quaternion                get_conjugate() const { return Quaternion(w, -x, -y, -z); }
    /// convert to OpenGL rotation matrix
    void                      get_matrix(float m[16]) const;

    /// add rotation represented by q to this quaternion
    Quaternion&               operator*=(const class Quaternion &q);
    /// return quaternion that represents roation of this object, followed by rotation
    /// represented by q
    Quaternion                operator* (const class Quaternion &q) const;
};

std::ostream& operator <<(std::ostream &o, const Quaternion &q);

#endif
